<template>
  <div class="container">
    <el-table ref="tableRef" :data="tableData" style="width: 100%;height: 100%" :span-method="objectSpanMethod" border>
      <el-table-column v-for="item in tableColumn" :key="item.prop" :prop="item.prop" :label="item.label" min-width="120" align="center" />
    </el-table>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, onUnmounted } from 'vue';
// 滚动效果
let timer = null
let tableRef = ref(null)
const scroll = ()=>{
  if (timer)clearInterval(timer)
  let status = true
  const scrollDom = tableRef.value.$refs.bodyWrapper.getElementsByClassName('el-scrollbar__wrap')[0]
  scrollDom.addEventListener('mouseover',()=>{
    status = false
  })
  scrollDom.addEventListener('mouseout',()=>{
    status = true
  })
  timer = setInterval(()=>{
    if(status){
      scrollDom.scrollTop += 40
      if((scrollDom.scrollHeight - (scrollDom.clientHeight + scrollDom.scrollTop)) < 1){
        scrollDom.scrollTop = 0
      }
    }
  },1000)
}

// 存放所有的表头 一定要与tableData一致
const colFields = reactive(["city", "name", "make", "finance", "energy", "education"]);

//存储合并单元格的开始位置
const spanArr = reactive([]);

// 表头数据
const tableColumn = reactive([
  { prop: 'city', label: '城市' },
  { prop: 'name', label: '区域' },
  { prop: 'make', label: '制造业' },
  { prop: 'finance', label: '金融业' },
  { prop: 'energy', label: '能源业' },
  { prop: 'education', label: '教育业' }
])

// 表格数据
const tableData = reactive([
  {
    "city": "北京",
    "name": "东城区",
    "make": "0.0",
    "finance": "65.0",
    "energy": "0.0",
    "education": "0.0"
  },
  {
    "city": "北京",
    "name": "西城区",
    "make": "0.0",
    "finance": "0.0",
    "energy": "0.0",
    "education": "60.0"
  },
  {
    "city": "北京",
    "name": "朝阳区",
    "make": "0.0",
    "finance": "0.0",
    "energy": "0.2",
    "education": "70.0"
  },
  {
    "city": "上海",
    "name": "黄埔区",
    "make": "0.0",
    "finance": "25.14",
    "energy": "67.14",
    "education": "55.8"
  },
  {
    "city": "上海",
    "name": "黄埔区",
    "make": "0.8",
    "finance": "7.84",
    "energy": "0.0",
    "education": "68.8"
  },
  {
    "city": "上海",
    "name": "静安区",
    "make": "25.15",
    "finance": "66.14",
    "energy": "58.25",
    "education": "68.8"
  },
  {
    "city": "广州",
    "name": "天河区",
    "make": "0.0",
    "finance": "0.0",
    "energy": "83.0",
    "education": "0.0"
  },
  {
    "city": "深圳",
    "name": "南山区",
    "make": "73.0",
    "finance": "0.0",
    "energy": "45.0",
    "education": "0.0"
  },
]);


// 获取并计算表格单元格合并信息
const getSpanArr = () => {
  for (let i = 0; i < tableData.length; i++) {
    let row = i;
    if (row === 0) {
      for (let j = 0; j < colFields.length; j++) {
        spanArr[i * colFields.length + j] = {
          rowspan: 1,
          colspan: 1,
        };
      }
    } else {
      for (let j = 0; j < colFields.length; j++) {
        // 如果当前行和上一行相同的数据，进行合并
        // 添加筛选条件 指定要合并哪些列
        if (colFields[j] == 'city' || colFields[j] == 'name' || colFields[j] == 'make' || colFields[j] == 'finance' || colFields[j] == 'energy' || colFields[j] == 'education') {
          // 动态合并相同数据单元格（指定列+合并条件）有时候我们会遇到不想合并的单元格 例如：交叉错开的合并
          // 哪些不合并: Grade不一样的,不合并 避免交叉错开的合并
          if (tableData[row]["city"] !== tableData[row - 1]["city"]) {
            spanArr[row * colFields.length + j] = {
              rowspan: 1,
              colspan: 1,
            };
          } else if (tableData[row][colFields[j]] === tableData[row - 1][colFields[j]]) {
            let beforeItem = spanArr[(row - 1) * colFields.length + j];
            spanArr[row * colFields.length + j] = {
              rowspan: 1 + beforeItem.rowspan, // 合并几行
              colspan: 1, // 这里只是跨行，不跨列
            };
            beforeItem.rowspan = 0;
            beforeItem.colspan = 0;
          } else {
            spanArr[row * colFields.length + j] = {
              rowspan: 1,
              colspan: 1,
            };
          }
        } else {
          spanArr[row * colFields.length + j] = {
            rowspan: 1,
            colspan: 1,
          };
        }
      }
    }
  }

  // 对数据进行倒序
  let stack = [];
  for (let i = 0; i < colFields.length; i++) {
    for (let j = 0; j < tableData.length; j++) {
      if (j === 0) {
        if (spanArr[j * colFields.length + i].rowspan === 0) {
          stack.push(spanArr[j * colFields.length + i]);
        }
      } else {
        if (spanArr[j * colFields.length + i].rowspan === 0) {
          stack.push(spanArr[j * colFields.length + i]);
        } else {
          stack.push(spanArr[j * colFields.length + i]);
          while (stack.length > 0) {
            let pop = stack.pop();
            let len = stack.length;
            spanArr[(j - len) * colFields.length + i] = pop;
          }
        }
      }
    }
  }
};

// 返回合并单元格的方法，供模板中使用
const objectSpanMethod = ({ rowIndex, columnIndex }) => {
  return spanArr[rowIndex * colFields.length + columnIndex];
};

onMounted(() => {
  // 在组件挂载时调用 getSpanArr
  getSpanArr();
  // 调用滚动方法
  setTimeout(()=>{
    scroll()
  })
});
// 销毁
onUnmounted(()=>{
  if(timer) clearInterval(timer)
  timer = null
})
</script>

<style scoped>
.container {
  width: 100%;
  height: 310px;
}
</style>
